<template>
  <div class="rolling-numbers">
    <div v-for="(item, index) in valueStrArr" :key="index" class="rolling-number" :class="[rollingClass]">
      <div class="number-group" :style="{ transform: `translateY(${ item.y }%)`, transitionDuration: `${ duration }ms` }">
        <div v-for="i in 10" :key="i" class="number-val" :class="{ 'is-placeholder': item.val === '#'}">{{ i - 1 }}</div>
        <div v-for="str in otherStr" :key="str" class="number-val">{{ str }}</div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, ref, watch, withDefaults } from 'vue'

const props = withDefaults(defineProps<{
  value: number | string,
  capacity?: number
  rollingClass?: string,
  duration: number,
}>(), {
  duration: 300,
  rollingClass: '',
  capacity: null
})

onMounted(() => {
  updateData('#')
  setTimeout(updateData, props.duration)
})

watch(() => props.value, () => {
  updateData()
})

const valueStrArr = ref<{val: string, y: number}[]>([])

/**
 * 格式化数据
 * @returns {string[]}
 */
const formattedData = (value: number|string) => {
  let valueArr = value.toString().split('')
  const capacity = props.capacity || props.value.toString().length
  if (valueArr.length < capacity) {
    valueArr = ''.padEnd(capacity - valueArr.length, '#').split('').concat(valueArr)
  }
  return valueArr
}
// 可容纳10个特殊符号
const otherStr = ['.', '-']

/**
 * 更新数据
 */
const updateData = (value?: number|string) => {
  valueStrArr.value = formattedData(value || props.value).map(val => {
    if (isNaN(Number(val))) {
      if (val === '#') {
        return { val, y: 0 }
      } else {
        return { val, y: -(otherStr.indexOf(val) * 5 + 50) }
      }
    } else {
      return { val, y: -val * 5 }
    }
  })
}
</script>

<style lang="scss" scoped>
.rolling-numbers{
  display: flex;
  .rolling-number{
    height: 1em;
    overflow: hidden;
    .number-group{
      width: 100%; height: 2000%;
      transition: all 1000ms;
      font-family: inherit;
    }
    .number-val{
      width: 100%; height: 5%;
      display: flex;
      justify-content: center;
      align-items: center;
      color: inherit;
      font-family: inherit;
      &.is-placeholder{
        opacity: .5;
      }
    }
  }
}
</style>
